package cn.bigfire.wedesk.net.codec;

import cn.bigfire.wedesk.net.fivesocket.frame.BinaryFiveFrame;
import cn.bigfire.wedesk.net.fivesocket.frame.TextFiveFrame;
import cn.bigfire.wedesk.net.protocol.Protocol;
import cn.bigfire.wedesk.net.protocol.TypeMapper;
import cn.bigfire.wedesk.util.ByteUtil;
import cn.bigfire.wedesk.util.ProtostuffUtil;
import com.alibaba.fastjson.JSON;

import com.google.protobuf.AbstractMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;

/**
 * 业务层 编解码器  编码和解码放在同一个类里
 */
@Deprecated
public class ProtocolCodec extends ChannelDuplexHandler {

    //解码
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            Protocol protocol = new Protocol();
            if (msg instanceof TextFiveFrame) {
                TextFiveFrame textFiveFrame = (TextFiveFrame) msg;
                protocol = JSON.parseObject(textFiveFrame.text(), Protocol.class);
                System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), textFiveFrame.text().length(), ByteUtil.size(textFiveFrame.text().length()));
                if (protocol.getCmd() != 0 && protocol.getObj() != null) {//有效数据再往下传递
                    ctx.fireChannelRead(protocol);
                }
            } else if (msg instanceof BinaryFiveFrame) {
                BinaryFiveFrame binaryFiveFrame = (BinaryFiveFrame) msg;
                ByteBuf content = binaryFiveFrame.content();
                int cmd = content.readInt();
                int type = content.readInt();
                byte[] bytes = new byte[content.readableBytes()];
                content.readBytes(bytes);
                protocol.setCmd(cmd);
                protocol.setType(type);
                Class<?> codec = TypeMapper.getCodec(type);
                protocol.setObj(ProtostuffUtil.deserializer(bytes, codec));
                if (protocol.getCmd() != 0 && protocol.getObj() != null) {//有效数据再往下传递
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), bytes.length, ByteUtil.size(bytes.length));
                    ctx.fireChannelRead(protocol);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    boolean isJson = false;//控制写数据时使用protobuf还是json
    //编码
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        try {
            if (msg instanceof Protocol) {
                Protocol protocol = (Protocol) msg;
                if (isJson) {
                    String jsonString = JSON.toJSONString(protocol);
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), jsonString.length(), ByteUtil.size(jsonString.length()));
                    TextFiveFrame textFiveFrame = new TextFiveFrame(jsonString);
                    super.write(ctx, textFiveFrame, promise);
                } else {
                    int cmd = protocol.getCmd();
                    int type = TypeMapper.getType(protocol.getObj().getClass());
                    byte[] bytes = new byte[0];
                    if (protocol.getObj() instanceof AbstractMessage) {
                        AbstractMessage abstractMessage = (AbstractMessage) protocol.getObj();
                        bytes = abstractMessage.toByteArray();
                    } else {
                        bytes = ProtostuffUtil.serializer(protocol.getObj());
                    }
                    ByteBuf outBuf = Unpooled.buffer();
                    outBuf.writeInt(cmd);
                    outBuf.writeInt(type);
                    outBuf.writeBytes(bytes);
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), bytes.length, ByteUtil.size(bytes.length));
                    BinaryFiveFrame binaryFiveFrame = new BinaryFiveFrame(outBuf);
                    super.write(ctx, binaryFiveFrame, promise);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
